﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Resources;
using System.Xml;
using System.IO;
using System.Net;
using System.Diagnostics;
using System.Xml.Linq;
using CardClass;

namespace CardTest
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        bool HasStarted = false;
        bool HasChar = false;
        bool HasRole = false;
        string isHost;

        const int InitialCardsNumber = 4;
        int PlayerNum = 0;
        string myID;

        private int Activity = -1;
        // 0 - kill
        // 1 - cure

        private WebClient webClient = new WebClient();
        //StreamResourceInfo zipResourceInfo;
        List<string> ListPlayer = new List<string>();
        Random random = new Random();

        CardControlChar cc = new CardControlChar();
        GameHandler Game;

        public Window1()
        {
            InitializeComponent();
            Game = new GameHandler (new EventHolder());
            this.Visibility = Visibility.Collapsed;

        }

        public void GetMessageFromServer(string message)
        {
            XDocument xdocument = XDocument.Parse(message);
            XElement root = xdocument.Element("message");
            Debug.Assert(root.Name == "message");

            IEnumerable<XElement> elements;
            Debug.WriteLine(root.Attribute("type").Value);

            switch (root.Attribute("type").Value)
            {
                case "joinResult":

                    if (root.Attribute("result").Value == "success")
                    {
                        XElement guid = root.Element("guid");
                        Game.messageController.SendMessage(guid.Value);


                        // Silverlight control initialize
                        //HtmlElement nameElement = HtmlPage.Document.GetElementById("DisplayName");
                        myID = DisplayName.Text;
                        isHost = root.Attribute("ishost").Value;

                        Visibility = Visibility.Visible;
                        if (isHost == "true")
                            Btn_Start.Visibility = Visibility.Visible;
                        Text_Status.Visibility = Visibility.Visible;
                        //ProgressIn.Begin();

                    }
                    else if (root.Attribute("result").Value == "fail")
                    {
                        XElement detail = root.Element("detail");
                        Game.messageController.ErrorAlert (detail.Value);
                        return;
                    }
                    break;
                case "playerList":
                    elements =
                        from el in root.Elements("player")
                        select el;

                    // Clear Players
                    ListPlayer.Clear();
                    PlayersPanel.Items.Clear();
                    PlayerNum = 0;

                    foreach (XElement element in elements)
                    {
                        string playername = element.Value;

                        if (!ListPlayer.Contains(playername))
                        {
                            GetPlayer(playername, "HP:", "Cards:");
                            ListPlayer.Add(playername);
                            PlayerNum++;

                            TextBlock tb = new TextBlock();
                            tb.TextDecorations = TextDecorations.Underline;
                            tb.Text = playername;
                            tb.Cursor = Cursors.Hand;
                            tb.MouseLeftButtonUp += new MouseButtonEventHandler(ActPerson_MouseLeftButtonUp);
                            tb.Foreground = new SolidColorBrush(Colors.Green);
                            tb.SetValue(Canvas.LeftProperty, 5);
                            tb.SetValue(Canvas.TopProperty, (PlayerNum - 1) * 20);
                            //UserLayer.Children.Add(tb);
                            bool flag = true;
                            foreach (TextBlock item in TargetsPanel.Items)
                            {
                                if (tb.Text == item.Text)
                                    flag = false;
                            }
                            if (flag)
                                TargetsPanel.Items.Add(tb);
                        }
                    }
                    break;

                case "startGameResult":
                    string result = root.Attribute("result").Value;
                    break;

                case "roleCard":
                    XElement role = root.Element("role");
                    GetRole(role.Value, "longda.png");
                    break;

                case "characterCard":
                    elements =
                        from el in root.Elements("character")
                        select el;
                    foreach (XElement element in elements)
                    {
                        var player = element.Attribute("player").Value;
                        var hp = element.Attribute("hp").Value;
                        var description = element.Attribute("description").Value;

                        // Update player list
                        foreach (PlayerPanel pp in PlayersPanel.Items)
                        {
                            if (pp.PlayerIDText == player)
                            {
                                pp.PlayerIDText = player + "   C:" + element.Value;
                                pp.HPText = "HP: " + hp + "/" + hp;
                                pp.CardsText = "Cards: 4";
                            }
                        }

                        if (myID == player)
                        {
                            GetChar(element.Value, "S:" + description, "HP: " + hp + "/" + hp, "yangweili.png");
                        }
                    }

                    break;

                case "gameCard":
                    elements =
                        from el in root.Elements("gameCard")
                        select el;
                    foreach (XElement element in elements)
                    {
                        GetCards(element.Value, element.Value + ".png");
                    }

                    break;

                case "dispatchCardFinish":
                    HasStarted = true;
                    TextBlock t = new TextBlock();
                    t.TextDecorations = TextDecorations.Underline;
                    t.Foreground = new SolidColorBrush(Colors.Purple);
                    t.Text = "Cancel";
                    t.MouseLeftButtonUp += new MouseButtonEventHandler(ActPerson_MouseLeftButtonUp);
                    t.Cursor = Cursors.Hand;
                    t.SetValue(Canvas.LeftProperty, 5);
                    t.SetValue(Canvas.TopProperty, PlayerNum * 20);
                    TargetsPanel.Items.Add(t);

                    TextPanel.Text = "Ready to start";
                    Action.Visibility = Visibility.Visible;

                    // functions for user activity
                    ActKill.MouseLeftButtonUp += new MouseButtonEventHandler(ActKill_MouseLeftButtonUp);
                    ActCure.MouseLeftButtonUp += new MouseButtonEventHandler(ActCure_MouseLeftButtonUp);
                    Text_Status.Text = "Game Starts";

                    //ActionPanelIn.Begin();         //??
                    break;

                case "playerAction":
                    XElement action = root.Element("action");
                    string actor;
                    string target;
                    switch (action.Attribute("type").Value)
                    {
                        case "kill":
                            actor = action.Attribute("player").Value;
                            target = action.Attribute("target").Value;
                            if (myID == target)
                            {
                                TextPanel.Text = actor + " is killing you";
                                //
                                string sufferMsg = "<message type=\"playerAction\"><action type=\"suffer\"></action></message>";
                                Game.messageController.SendMessage(sufferMsg);
                            }
                            else if (myID == actor)
                            {
                                TextPanel.Text = "you are killing " + target;
                            }
                            else
                            {
                                TextPanel.Text = actor + " is killing " + target;
                            }
                            break;
                        case "cure":
                            actor = action.Attribute("player").Value;
                            target = action.Attribute("target").Value;
                            break;
                        case "miss":
                            actor = action.Attribute("player").Value;
                            break;
                        case "suffer":
                            actor = action.Attribute("player").Value;
                            if (myID == actor)
                            {
                                string[] b = cc.HPText.Substring(4).Split('/');
                                cc.HPText = "HP: " + (Int32.Parse(b[0]) - 1).ToString() + "/" + b[1];
                            }

                            foreach (PlayerPanel pp in PlayersPanel.Items)
                            {
                                string str = pp.PlayerIDText.Substring(0, pp.PlayerIDText.IndexOf(' '));
                                if (str == actor)
                                {
                                    string[] b = pp.HPText.Substring(4).Split('/');
                                    pp.HPText = "HP: " + (Int32.Parse(b[0]) - 1).ToString() + "/" + b[1];
                                }
                            }

                            break;
                    }

                    break;
                case "userLeaveResult":
                    if (root.Attribute("result").Value == "success")
                    {
                        this.Visibility = Visibility.Collapsed;
                    }

                    break;

            }
        }

        void ActPerson_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            TextBlock tb = sender as TextBlock;
            if (tb.Text == "cancel")
            {
                Activity = -1;
                TextPanel.Text = "Cancel";
                UserLayer.Visibility = Visibility.Collapsed;
                return;
            }

            String messageStr;
            switch (Activity)
            {
                case 0:
                    if (tb.Text == myID)
                    {
                        TextPanel.Text = "Cannot kill yourself";
                        UserLayer.Visibility = Visibility.Collapsed;
                        return;
                    }
                    TextPanel.Text = "Kill " + tb.Text;
                    messageStr = "<message type=\"playerAction\"><action type=\"kill\" target=\"" + tb.Text + "\"></action></message>";
                    //SendMessage(messageStr);
                    Game.messageController.SendMessage(messageStr);

                    break;

                case 1:
                    TextPanel.Text = "Cure " + tb.Text;
                    messageStr = "<message type=\"playerAction\"><action type=\"kill\" target=\"[" + tb.Text + "]\"></action></message>";
                    Game.messageController.SendMessage(messageStr);

                    break;
            }
            UserLayer.Visibility = Visibility.Collapsed;
            return;

        }

        void ActCure_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            bool flag = false;
            foreach (var card in CardsPanel.Children)
            {
                CardControlAction actioncard = card as CardControlAction;
                if (actioncard == null)
                    continue;
                if (actioncard.funcText == "Cure")
                {
                    flag = true;
                    break;
                }
            }
            if (!flag)
            {
                TextPanel.Text = "No Cure in your cards";
                return;
            }

            ClearActs();
            Activity = 1;
            ActCure.Foreground = new SolidColorBrush(Colors.Green);
            UserLayer.SetValue(Canvas.LeftProperty, e.GetPosition(null).X + 30);
            UserLayer.SetValue(Canvas.TopProperty, e.GetPosition(null).Y);
            UserLayer.SetValue(Canvas.ZIndexProperty, 100);
            UserLayer.Visibility = Visibility.Visible;

            foreach (var findMe in TargetsPanel.Items)
            {
                TextBlock tb = findMe as TextBlock;
                if (tb == null)
                    continue;
                if (tb.Text == "cancel")
                    tb.Foreground = new SolidColorBrush(Colors.Purple);
                else
                    tb.Foreground = new SolidColorBrush(Colors.Green);
            }
        }

        void ActKill_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            bool flag = false;
            foreach (var card in CardsPanel.Children)
            {
                CardControlAction actioncard = card as CardControlAction;
                if (actioncard == null)
                    continue;
                if (actioncard.funcText == "Kill")
                {
                    flag = true;
                    break;
                }
            }
            if (!flag)
            {
                TextPanel.Text = "No Kill in your cards";
                return;
            }

            ClearActs();
            Activity = 0;
            ActKill.Foreground = new SolidColorBrush(Colors.Red);
            UserLayer.SetValue(Canvas.LeftProperty, e.GetPosition(null).X + 30);
            UserLayer.SetValue(Canvas.TopProperty, e.GetPosition(null).Y);
            UserLayer.SetValue(Canvas.ZIndexProperty, 100);
            UserLayer.Visibility = Visibility.Visible;

            foreach (var findMe in TargetsPanel.Items)
            {
                TextBlock tb = findMe as TextBlock;
                if (tb == null)
                    continue;
                if (tb.Text == myID)
                    tb.Foreground = new SolidColorBrush(Colors.Gray);
                else if (tb.Text == "cancel")
                    tb.Foreground = new SolidColorBrush(Colors.Purple);
                else
                    tb.Foreground = new SolidColorBrush(Colors.Green);
            }
        }

        void ClearActs()
        {
            ActKill.Foreground = new SolidColorBrush(Colors.Black);
            ActCure.Foreground = new SolidColorBrush(Colors.Black);
        }

        private void StartGame(object o, EventArgs e)
        {
            if (HasStarted)
                return;
            Btn_Start.Visibility = Visibility.Collapsed;
            Game.messageController.SendMessage(QueryString("startGame"));
        }

        private void GetRole(string role, string image)
        {
            if (HasRole)
                return;
            // Role Card Distribution
            CardControlRole cr = new CardControlRole();
            cr.RoleText = role; //

            cr.SetURI(image); // 

            cr.Left = 510;
            cr.Top = 90;
            CardsPanel.Children.Add(cr);
            HasRole = true;
        }

        private void GetChar(string charactor, string skill, string hp, string image)
        {
            if (HasChar)
                return;
            // Character Card Distribution
            cc.CharText = charactor; // 
            cc.SkillText = skill; // 
            cc.HPText = hp; // 
            cc.SetURI(image); //

            cc.Left = 410;
            cc.Top = 70;
            //cc.Angle = (r.NextDouble() - 0.5) * 60;

            CardsPanel.Children.Add(cc);
            HasChar = true;
        }

        private void GetCards(string func, string image/*, int index*/)
        {
            // Character Card Distribution

            CardControlAction cc = new CardControlAction();
            cc.funcText = func;
            cc.SetURI(image);

            cc.Left = random.NextDouble() * 350;
            cc.Top = random.NextDouble() * 80;
            cc.Angle = (random.NextDouble() - 0.5) * 60;

            CardsPanel.Children.Add(cc);
        }

        private void GetPlayer(string playerid, string hp, string cards)
        {
            PlayerPanel pr = new PlayerPanel();
            pr.PlayerIDText = playerid;
            pr.HPText = hp;
            pr.CardsText = cards;

            pr.Left = 0;
            pr.Top = 0;

            PlayersPanel.Items.Add(pr);
        }

        private string QueryString(string type)
        {
            return "<message type=\"" + type + "\"></message>";
        }

        private void Btn_Register_Click(object sender, RoutedEventArgs e)
        {
            if (DisplayName.Text != "")
            {
                GameHandler.RegisterReturns r = Game.Join(this.DisplayName.Text);
                if (r == GameHandler.RegisterReturns.Success)
                {
                    MessageBox.Show("Join successed.");
                }
                else if (r == GameHandler.RegisterReturns.UsedPlayerName)
                    MessageBox.Show("This name has been used, please input another one.");
                else
                    MessageBox.Show("Unknown error.");
            }
            else
                MessageBox.Show("Please input your player name.");
        }

        private void Btn_Leave_Click(object sender, RoutedEventArgs e)
        {
            MessageBoxResult r = MessageBox.Show("Are you sure to leave?", "Leave?", MessageBoxButton.YesNo, MessageBoxImage.Warning) ;
           if (r.ToString() == "Yes")
                Game.messageController.SendMessage("<message type=\"userLeave\"/>");
        }

        public void SucceedJoined(string args)
        {
            Btn_Leave.Visibility = Visibility.Visible;
            Game.messageController.guid = args;
            Game.messageController.getMessage(new object());
        }


        
    }
}
